namespace ConcurrentBoo

import System
import System.Threading
	
class ComputationFailureException(Exception):
	def constructor(x as Exception):
		super(x.Message, x)
		
class Computation:
	
	public static final Nothing = object()	
	"""
	A Computation for methods returning no useful value (void)
	uses Nothing to signal a successful computation.
	"""
	
	private _finished = false
	
	private _failure as Exception
	
	private _value = null
	
	def constructor():
		pass
		
	HasFinishedWithFailure:
		[lock]
		get:
			if _finished: return _failure is not null
			return false
		
	Value:
	"""
	Retrieves the value of the computation blocking until it's available.
	
	@returns the computed value
	@throws ComputationFailureException when the computation terminates exceptionally
	"""
		[lock]
		get:
			EnsureFinished()
			EnsureSuccessful()
			return _value
		
		[lock]
		set:
			_value = value
			NotifyFinished()
			
	Failure:
	"""
	The exception if any that caused the computation to fail.
	"""
		[lock]
		get:
			EnsureFinished()
			return _failure
		
		[lock]
		set:
			_failure = value
			NotifyFinished()	
		
	[lock]
	def Wait(millisecondsTimeout as long):
	"""
	Blocks until the computation is finished or millisecondsTimeout is elapsed.
	"""
		return EnsureFinished(millisecondsTimeout)		
		
	[lock]
	def Wait():	
	"""
	Blocks until the computation is finished. Same as Wait(Timeout.Infinite).
	"""
		EnsureFinished()
			
	private def EnsureFinished():
		EnsureFinished(Timeout.Infinite)
		
	private def EnsureFinished(millisecondsTimeout as int):
		if _finished: return true
		return Monitor.Wait(self, millisecondsTimeout)
		
	private def EnsureSuccessful():
		if _failure is null: return
		raise ComputationFailureException(_failure)
		
	private def NotifyFinished():
		_finished = true
		Monitor.PulseAll(self)
